home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / BLEND.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-16  |  18.4 KB  |  629 lines

  1. /* $Id: blend.c,v 3.8 1998/08/16 14:44:56 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: blend.c,v $
  26.  * Revision 3.8  1998/08/16 14:44:56  brianp
  27.  * fixed arithmetic problems in blend_transparency() (Karl Schultz)
  28.  *
  29.  * Revision 3.7  1998/08/05 01:34:40  brianp
  30.  * fixed round-off problem exposed by conformance testing
  31.  *
  32.  * Revision 3.6  1998/07/09 03:15:22  brianp
  33.  * include asm_mmx.h instead of asm-mmx.h
  34.  *
  35.  * Revision 3.5  1998/04/22 00:53:02  brianp
  36.  * fixed a few more IRIX compiler warnings
  37.  *
  38.  * Revision 3.4  1998/03/28 03:57:13  brianp
  39.  * added CONST macro to fix IRIX compilation problems
  40.  *
  41.  * Revision 3.3  1998/03/28 02:03:22  brianp
  42.  * hooked in MMX code
  43.  *
  44.  * Revision 3.2  1998/02/13 04:38:05  brianp
  45.  * optimized blending functions called via BlendFunc function pointer
  46.  *
  47.  * Revision 3.1  1998/02/08 20:16:50  brianp
  48.  * removed unneeded headers
  49.  *
  50.  * Revision 3.0  1998/01/31 20:47:46  brianp
  51.  * initial rev
  52.  *
  53.  */
  54.  
  55.  
  56. #ifdef PC_HEADER
  57. #include "all.h"
  58. #else
  59. #include <assert.h>
  60. #include <stdlib.h>
  61. #include "alphabuf.h"
  62. #include "asm_mmx.h"
  63. #include "blend.h"
  64. #include "context.h"
  65. #include "macros.h"
  66. #include "pb.h"
  67. #include "span.h"
  68. #include "types.h"
  69. #endif
  70.  
  71.  
  72.  
  73. void gl_BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
  74. {
  75.    if (INSIDE_BEGIN_END(ctx)) {
  76.       gl_error( ctx, GL_INVALID_OPERATION, "glBlendFunc" );
  77.       return;
  78.    }
  79.  
  80.    switch (sfactor) {
  81.       case GL_ZERO:
  82.       case GL_ONE:
  83.       case GL_DST_COLOR:
  84.       case GL_ONE_MINUS_DST_COLOR:
  85.       case GL_SRC_ALPHA:
  86.       case GL_ONE_MINUS_SRC_ALPHA:
  87.       case GL_DST_ALPHA:
  88.       case GL_ONE_MINUS_DST_ALPHA:
  89.       case GL_SRC_ALPHA_SATURATE:
  90.       case GL_CONSTANT_COLOR:
  91.       case GL_ONE_MINUS_CONSTANT_COLOR:
  92.       case GL_CONSTANT_ALPHA:
  93.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  94.          ctx->Color.BlendSrc = sfactor;
  95.          break;
  96.       default:
  97.          gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
  98.          return;
  99.    }
  100.  
  101.    switch (dfactor) {
  102.       case GL_ZERO:
  103.       case GL_ONE:
  104.       case GL_SRC_COLOR:
  105.       case GL_ONE_MINUS_SRC_COLOR:
  106.       case GL_SRC_ALPHA:
  107.       case GL_ONE_MINUS_SRC_ALPHA:
  108.       case GL_DST_ALPHA:
  109.       case GL_ONE_MINUS_DST_ALPHA:
  110.       case GL_CONSTANT_COLOR:
  111.       case GL_ONE_MINUS_CONSTANT_COLOR:
  112.       case GL_CONSTANT_ALPHA:
  113.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  114.          ctx->Color.BlendDst = dfactor;
  115.          break;
  116.       default:
  117.          gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
  118.          return;
  119.    }
  120.  
  121.    ctx->Color.BlendFunc = NULL;
  122.    ctx->NewState |= NEW_RASTER_OPS;
  123. }
  124.  
  125.  
  126.  
  127. /* This is really an extension function! */
  128. void gl_BlendEquation( GLcontext *ctx, GLenum mode )
  129. {
  130.    if (INSIDE_BEGIN_END(ctx)) {
  131.       gl_error( ctx, GL_INVALID_OPERATION, "glBlendEquation" );
  132.       return;
  133.    }
  134.  
  135.    switch (mode) {
  136.       case GL_MIN_EXT:
  137.       case GL_MAX_EXT:
  138.       case GL_LOGIC_OP:
  139.       case GL_FUNC_ADD_EXT:
  140.       case GL_FUNC_SUBTRACT_EXT:
  141.       case GL_FUNC_REVERSE_SUBTRACT_EXT:
  142.          ctx->Color.BlendEquation = mode;
  143.          break;
  144.       default:
  145.          gl_error( ctx, GL_INVALID_ENUM, "glBlendEquation" );
  146.          return;
  147.    }
  148.  
  149.    /* This is needed to support 1.1's RGB logic ops AND
  150.     * 1.0's blending logicops.
  151.     */
  152.    if (mode==GL_LOGIC_OP && ctx->Color.BlendEnabled) {
  153.       ctx->Color.ColorLogicOpEnabled = GL_TRUE;
  154.    }
  155.    else {
  156.       ctx->Color.ColorLogicOpEnabled = GL_FALSE;
  157.    }
  158.  
  159.    ctx->Color.BlendFunc = NULL;
  160.    ctx->NewState |= NEW_RASTER_OPS;
  161. }
  162.  
  163.  
  164.  
  165. void gl_BlendColor( GLcontext *ctx, GLclampf red, GLclampf green,
  166.             GLclampf blue, GLclampf alpha )
  167. {
  168.    ctx->Color.BlendColor[0] = CLAMP( red,   0.0, 1.0 );
  169.    ctx->Color.BlendColor[1] = CLAMP( green, 0.0, 1.0 );
  170.    ctx->Color.BlendColor[2] = CLAMP( blue,  0.0, 1.0 );
  171.    ctx->Color.BlendColor[3] = CLAMP( alpha, 0.0, 1.0 );
  172. }
  173.  
  174.  
  175.  
  176. /*
  177.  * Common transparency blending mode.
  178.  */
  179. static void blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
  180.                                 GLubyte rgba[][4], CONST GLubyte dest[][4] )
  181. {
  182.    GLuint i;
  183.    ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
  184.    ASSERT(ctx->Color.BlendSrc==GL_SRC_ALPHA);
  185.    ASSERT(ctx->Color.BlendDst==GL_ONE_MINUS_SRC_ALPHA);
  186.  
  187.    for (i=0;i<n;i++) {
  188.       if (mask[i]) {
  189.          GLint t = rgba[i][ACOMP];  /* t in [0,255] */
  190.          if (t == 0) {
  191.             rgba[i][RCOMP] = dest[i][RCOMP];
  192.             rgba[i][GCOMP] = dest[i][GCOMP];
  193.             rgba[i][BCOMP] = dest[i][BCOMP];
  194.             rgba[i][ACOMP] = dest[i][ACOMP];
  195.          }
  196.          else if (t == 255) {
  197.             /* no-op */
  198.          }
  199.          else {
  200.             GLint s = 255 - t;
  201.             GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) >> 8;
  202.             GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) >> 8;
  203.             GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) >> 8;
  204.             GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) >> 8;
  205.             ASSERT(r <= 255);
  206.             ASSERT(g <= 255);
  207.             ASSERT(b <= 255);
  208.             ASSERT(a <= 255);
  209.             rgba[i][RCOMP] = r;
  210.             rgba[i][GCOMP] = g;
  211.             rgba[i][BCOMP] = b;
  212.             rgba[i][ACOMP] = a;
  213.          }
  214.       }
  215.    }
  216. }
  217.  
  218.  
  219.  
  220. /*
  221.  * Add src and dest.
  222.  */
  223. static void blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
  224.                        GLubyte rgba[][4], CONST GLubyte dest[][4] )
  225. {
  226.    GLuint i;
  227.    ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
  228.    ASSERT(ctx->Color.BlendSrc==GL_ONE);
  229.    ASSERT(ctx->Color.BlendDst==GL_ONE);
  230.    (void) ctx;
  231.  
  232.    for (i=0;i<n;i++) {
  233.       if (mask[i]) {
  234.          GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
  235.          GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
  236.          GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
  237.          GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
  238.          rgba[i][RCOMP] = MIN2( r, 255 );
  239.          rgba[i][GCOMP] = MIN2( g, 255 );
  240.          rgba[i][BCOMP] = MIN2( b, 255 );
  241.          rgba[i][ACOMP] = MIN2( a, 255 );
  242.       }
  243.    }
  244. }
  245.  
  246.  
  247.  
  248. /*
  249.  * Blend min function  (for GL_EXT_blend_minmax)
  250.  */
  251. static void blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
  252.                        GLubyte rgba[][4], CONST GLubyte dest[][4] )
  253. {
  254.    GLuint i;
  255.    ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT);
  256.    (void) ctx;
  257.  
  258.    for (i=0;i<n;i++) {
  259.       if (mask[i]) {
  260.          rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
  261.          rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
  262.          rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
  263.          rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
  264.       }
  265.    }
  266. }
  267.  
  268.  
  269.  
  270. /*
  271.  * Blend max function  (for GL_EXT_blend_minmax)
  272.  */
  273. static void blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
  274.                        GLubyte rgba[][4], CONST GLubyte dest[][4] )
  275. {
  276.    GLuint i;
  277.    ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT);
  278.    (void) ctx;
  279.  
  280.    for (i=0;i<n;i++) {
  281.       if (mask[i]) {
  282.          rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
  283.          rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
  284.          rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
  285.          rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
  286.       }
  287.    }
  288. }
  289.  
  290.  
  291.  
  292. /*
  293.  * Modulate:  result = src * dest
  294.  */
  295. static void blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
  296.                             GLubyte rgba[][4], CONST GLubyte dest[][4] )
  297. {
  298.    GLuint i;
  299.    (void) ctx;
  300.  
  301.    for (i=0;i<n;i++) {
  302.       if (mask[i]) {
  303.          GLint r = (rgba[i][RCOMP] * dest[i][RCOMP]) >> 8;
  304.          GLint g = (rgba[i][GCOMP] * dest[i][GCOMP]) >> 8;
  305.          GLint b = (rgba[i][BCOMP] * dest[i][BCOMP]) >> 8;
  306.          GLint a = (rgba[i][ACOMP] * dest[i][ACOMP]) >> 8;
  307.          rgba[i][RCOMP] = r;
  308.          rgba[i][GCOMP] = g;
  309.          rgba[i][BCOMP] = b;
  310.          rgba[i][ACOMP] = a;
  311.       }
  312.    }
  313. }
  314.  
  315.  
  316.  
  317. /*
  318.  * General case blend pixels.
  319.  * Input:  n - number of pixels
  320.  *         mask - the usual write mask
  321.  * In/Out:  rgba - the incoming and modified pixels
  322.  * Input:  dest - the pixels from the dest color buffer
  323.  */
  324. static void blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
  325.                            GLubyte rgba[][4], CONST GLubyte dest[][4] )
  326. {
  327.    GLfloat rscale = 1.0F / 255.0F;
  328.    GLfloat gscale = 1.0F / 255.0F;
  329.    GLfloat bscale = 1.0F / 255.0F;
  330.    GLfloat ascale = 1.0F / 255.0F;
  331.    GLuint i;
  332.  
  333.    for (i=0;i<n;i++) {
  334.       if (mask[i]) {
  335.          GLint Rs, Gs, Bs, As;  /* Source colors */
  336.          GLint Rd, Gd, Bd, Ad;  /* Dest colors */
  337.          GLfloat sR, sG, sB, sA;  /* Source scaling */
  338.          GLfloat dR, dG, dB, dA;  /* Dest scaling */
  339.          GLfloat r, g, b, a;
  340.  
  341.          /* Source Color */
  342.          Rs = rgba[i][RCOMP];
  343.          Gs = rgba[i][GCOMP];
  344.          Bs = rgba[i][BCOMP];
  345.          As = rgba[i][ACOMP];
  346.  
  347.          /* Frame buffer color */
  348.          Rd = dest[i][RCOMP];
  349.          Gd = dest[i][GCOMP];
  350.          Bd = dest[i][BCOMP];
  351.          Ad = dest[i][ACOMP];
  352.  
  353.          /* Source scaling */
  354.          switch (ctx->Color.BlendSrc) {
  355.             case GL_ZERO:
  356.                sR = sG = sB = sA = 0.0F;
  357.                break;
  358.             case GL_ONE:
  359.                sR = sG = sB = sA = 1.0F;
  360.                break;
  361.             case GL_DST_COLOR:
  362.                sR = (GLfloat) Rd * rscale;
  363.                sG = (GLfloat) Gd * gscale;
  364.                sB = (GLfloat) Bd * bscale;
  365.                sA = (GLfloat) Ad * ascale;
  366.                break;
  367.             case GL_ONE_MINUS_DST_COLOR:
  368.                sR = 1.0F - (GLfloat) Rd * rscale;
  369.                sG = 1.0F - (GLfloat) Gd * gscale;
  370.                sB = 1.0F - (GLfloat) Bd * bscale;
  371.                sA = 1.0F - (GLfloat) Ad * ascale;
  372.                break;
  373.             case GL_SRC_ALPHA:
  374.                sR = sG = sB = sA = (GLfloat) As * ascale;
  375.                break;
  376.             case GL_ONE_MINUS_SRC_ALPHA:
  377.                sR = sG = sB = sA = (GLfloat) 1.0F - (GLfloat) As * ascale;
  378.                break;
  379.             case GL_DST_ALPHA:
  380.                sR = sG = sB = sA =(GLfloat) Ad * ascale;
  381.                break;
  382.             case GL_ONE_MINUS_DST_ALPHA:
  383.                sR = sG = sB = sA = 1.0F - (GLfloat) Ad * ascale;
  384.                break;
  385.             case GL_SRC_ALPHA_SATURATE:
  386.                if (As < 1.0F - (GLfloat) Ad * ascale) {
  387.                   sR = sG = sB = (GLfloat) As * ascale;
  388.                }
  389.                else {
  390.                   sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
  391.                }
  392.                sA = 1.0;
  393.                break;
  394.             case GL_CONSTANT_COLOR:
  395.                sR = ctx->Color.BlendColor[0];
  396.                sG = ctx->Color.BlendColor[1];
  397.                sB = ctx->Color.BlendColor[2];
  398.                sA = ctx->Color.BlendColor[3];
  399.                break;
  400.             case GL_ONE_MINUS_CONSTANT_COLOR:
  401.                sR = 1.0F - ctx->Color.BlendColor[0];
  402.                sG = 1.0F - ctx->Color.BlendColor[1];
  403.                sB = 1.0F - ctx->Color.BlendColor[2];
  404.                sA = 1.0F - ctx->Color.BlendColor[3];
  405.                break;
  406.             case GL_CONSTANT_ALPHA:
  407.                sR = sG = sB = sA = ctx->Color.BlendColor[3];
  408.                break;
  409.             case GL_ONE_MINUS_CONSTANT_ALPHA:
  410.                sR = sG = sB = sA = 1.0F - ctx->Color.BlendColor[3];
  411.                break;
  412.             default:
  413.                /* this should never happen */
  414.                gl_problem(ctx, "Bad blend source factor in do_blend");
  415.          }
  416.  
  417.          /* Dest scaling */
  418.          switch (ctx->Color.BlendDst) {
  419.             case GL_ZERO:
  420.                dR = dG = dB = dA = 0.0F;
  421.                break;
  422.             case GL_ONE:
  423.                dR = dG = dB = dA = 1.0F;
  424.                break;
  425.             case GL_SRC_COLOR:
  426.                dR = (GLfloat) Rs * rscale;
  427.                dG = (GLfloat) Gs * gscale;
  428.                dB = (GLfloat) Bs * bscale;
  429.                dA = (GLfloat) As * ascale;
  430.                break;
  431.             case GL_ONE_MINUS_SRC_COLOR:
  432.                dR = 1.0F - (GLfloat) Rs * rscale;
  433.                dG = 1.0F - (GLfloat) Gs * gscale;
  434.                dB = 1.0F - (GLfloat) Bs * bscale;
  435.                dA = 1.0F - (GLfloat) As * ascale;
  436.                break;
  437.             case GL_SRC_ALPHA:
  438.                dR = dG = dB = dA = (GLfloat) As * ascale;
  439.                break;
  440.             case GL_ONE_MINUS_SRC_ALPHA:
  441.                dR = dG = dB = dA = (GLfloat) 1.0F - (GLfloat) As * ascale;
  442.                break;
  443.             case GL_DST_ALPHA:
  444.                dR = dG = dB = dA = (GLfloat) Ad * ascale;
  445.                break;
  446.             case GL_ONE_MINUS_DST_ALPHA:
  447.                dR = dG = dB = dA = 1.0F - (GLfloat) Ad * ascale;
  448.                break;
  449.             case GL_CONSTANT_COLOR:
  450.                dR = ctx->Color.BlendColor[0];
  451.                dG = ctx->Color.BlendColor[1];
  452.                dB = ctx->Color.BlendColor[2];
  453.                dA = ctx->Color.BlendColor[3];
  454.                break;
  455.             case GL_ONE_MINUS_CONSTANT_COLOR:
  456.                dR = 1.0F - ctx->Color.BlendColor[0];
  457.                dG = 1.0F - ctx->Color.BlendColor[1];
  458.                dB = 1.0F - ctx->Color.BlendColor[2];
  459.                dA = 1.0F - ctx->Color.BlendColor[3];
  460.                break;
  461.             case GL_CONSTANT_ALPHA:
  462.                dR = dG = dB = dA = ctx->Color.BlendColor[3];
  463.                break;
  464.             case GL_ONE_MINUS_CONSTANT_ALPHA:
  465.                dR = dG = dB = dA = 1.0F - ctx->Color.BlendColor[3] * ascale;
  466.                break;
  467.             default:
  468.                /* this should never happen */
  469.                gl_problem(ctx, "Bad blend dest factor in do_blend");
  470.          }
  471.  
  472.          /* Due to round-off problems we have to clamp against zero. */
  473.          /* Optimization: we don't have to do this for all src & dst factors */
  474.          if (dA < 0.0F)  dA = 0.0F;
  475.          if (dR < 0.0F)  dR = 0.0F;
  476.          if (dG < 0.0F)  dG = 0.0F;
  477.          if (dB < 0.0F)  dB = 0.0F;
  478.          if (sA < 0.0F)  sA = 0.0F;
  479.          if (sR < 0.0F)  sR = 0.0F;
  480.          if (sG < 0.0F)  sG = 0.0F;
  481.          if (sB < 0.0F)  sB = 0.0F;
  482.  
  483.          ASSERT( sR <= 1.0 );
  484.          ASSERT( sG <= 1.0 );
  485.          ASSERT( sB <= 1.0 );
  486.          ASSERT( sA <= 1.0 );
  487.          ASSERT( dR <= 1.0 );
  488.          ASSERT( dG <= 1.0 );
  489.          ASSERT( dB <= 1.0 );
  490.          ASSERT( dA <= 1.0 );
  491.  
  492.          /* compute blended color */
  493.          if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
  494.             r = Rs * sR + Rd * dR;
  495.             g = Gs * sG + Gd * dG;
  496.             b = Bs * sB + Bd * dB;
  497.             a = As * sA + Ad * dA;
  498.          }
  499.          else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
  500.             r = Rs * sR - Rd * dR;
  501.             g = Gs * sG - Gd * dG;
  502.             b = Bs * sB - Bd * dB;
  503.             a = As * sA - Ad * dA;
  504.          }
  505.          else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
  506.             r = Rd * dR - Rs * sR;
  507.             g = Gd * dG - Gs * sG;
  508.             b = Bd * dB - Bs * sB;
  509.             a = Ad * dA - As * sA;
  510.          }
  511.  
  512.          /* final clamping */
  513.          rgba[i][RCOMP] = (GLint) CLAMP( r, 0.0F, 255.0F );
  514.          rgba[i][GCOMP] = (GLint) CLAMP( g, 0.0F, 255.0F );
  515.          rgba[i][BCOMP] = (GLint) CLAMP( b, 0.0F, 255.0F );
  516.          rgba[i][ACOMP] = (GLint) CLAMP( a, 0.0F, 255.0F );
  517.       }
  518.    }
  519. }
  520.  
  521.  
  522.  
  523. /*
  524.  * Analyze current blending parameters to pick fastest blending function.
  525.  * Result: the ctx->Color.BlendFunc pointer is updated.
  526.  */
  527. static void set_blend_function(GLcontext *ctx)
  528. {
  529.    GLenum eq = ctx->Color.BlendEquation;
  530.    GLenum src = ctx->Color.BlendSrc;
  531.    GLenum dst = ctx->Color.BlendDst;
  532.  
  533.    if (eq==GL_FUNC_ADD_EXT && src==GL_SRC_ALPHA && dst==GL_ONE_MINUS_SRC_ALPHA) {
  534. #ifdef MMX
  535.       ctx->Color.BlendFunc = gl_mmx_blend_transparency;
  536. #else
  537.       ctx->Color.BlendFunc = blend_transparency;
  538. #endif
  539.    }
  540.    else if (eq==GL_FUNC_ADD_EXT && src==GL_ONE && dst==GL_ONE) {
  541.       ctx->Color.BlendFunc = blend_add;
  542.    }
  543.    else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT)
  544.              && (src==GL_ZERO && dst==GL_SRC_COLOR))
  545.             ||
  546.             ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT)
  547.              && (src==GL_DST_COLOR && dst==GL_ZERO))) {
  548.       ctx->Color.BlendFunc = blend_modulate;
  549.    }
  550.    else if (eq==GL_MIN_EXT) {
  551.       ctx->Color.BlendFunc = blend_min;
  552.    }
  553.    else if (eq==GL_MAX_EXT) {
  554.       ctx->Color.BlendFunc = blend_max;
  555.    }
  556.    else {
  557.       ctx->Color.BlendFunc = blend_general;
  558.    }
  559. }
  560.  
  561.  
  562.  
  563. /*
  564.  * Apply the blending operator to a span of pixels.
  565.  * Input:  n - number of pixels in span
  566.  *         x, y - location of leftmost pixel in span in window coords.
  567.  *         mask - boolean mask indicating which pixels to blend.
  568.  * In/Out:  rgba - pixel values
  569.  */
  570. void gl_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
  571.             GLubyte rgba[][4], const GLubyte mask[] )
  572. {
  573.    GLubyte dest[MAX_WIDTH][4];
  574.  
  575.    /* Check if device driver can do the work */
  576.    if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
  577.       return;
  578.    }
  579.  
  580.    /* Read span of current frame buffer pixels */
  581.    gl_read_rgba_span( ctx, n, x, y, dest );
  582.  
  583.    if (!ctx->Color.BlendFunc)
  584.       set_blend_function(ctx);
  585.  
  586.    (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, dest );
  587. }
  588.  
  589.  
  590.  
  591.  
  592.  
  593. /*
  594.  * Apply the blending operator to an array of pixels.
  595.  * Input:  n - number of pixels in span
  596.  *         x, y - array of pixel locations
  597.  *         mask - boolean mask indicating which pixels to blend.
  598.  * In/Out:  rgba - pixel values
  599.  */
  600. void gl_blend_pixels( GLcontext *ctx,
  601.                       GLuint n, const GLint x[], const GLint y[],
  602.               GLubyte rgba[][4], const GLubyte mask[] )
  603. {
  604.    GLubyte dest[PB_SIZE][4];
  605.  
  606.    /* Check if device driver can do the work */
  607.    if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
  608.       return;
  609.    }
  610.  
  611.    /* Read pixels from current color buffer */
  612.    (*ctx->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask );
  613.  
  614.    if (ctx->RasterMask & ALPHABUF_BIT) {
  615.       gl_read_alpha_pixels( ctx, n, x, y, dest, mask );
  616.    }
  617.    else {
  618.       GLuint i;
  619.       for (i=0; i<n; i++) {
  620.          dest[i][ACOMP] = 255;
  621.       }
  622.    }
  623.  
  624.    if (!ctx->Color.BlendFunc)
  625.       set_blend_function(ctx);
  626.  
  627.    (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, dest );
  628. }
  629.